import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:aero_frisbee/app/conf/app_env.dart';
import 'package:aero_frisbee/app/store/app_store.dart';
import 'package:aero_frisbee/core/http/dio_interceptors.dart';
import 'package:crypto/crypto.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:dio/dio.dart';
import 'package:flutter_udid/flutter_udid.dart';
import 'package:get_it/get_it.dart';
import 'package:package_info_plus/package_info_plus.dart';

class AFLogPages {
  static const String launch = "launch";
  static const String quickLogin = "quicklogin";
  static const String appleLogin = "applelogin";
  static const String terms = "terms";
  static const String privacy = "privacy";
  static const String loginSuccess = "loginsuccess";
  static const String purchase = "purchase";
  static const String createOrder = "createorder";
  static const String editAvatar = "editavatar";
  static const String logout = "logout";
  static const String deleteAccount = "deleteaccount";
  static const String customer = "customer";
  static const String report = "report";
  static const String block = "block";
  static const String tabHome = "tabhome";
  static const String tabFind = "tabfind";
  static const String tabChat = "tabchat";
  static const String tabMe = "tabme";
}

class AFLogPvManger {
  AFLogPvManger._();

  static const String _event = 'event';
  static const String _tm = 'tm';
  static const String _page = 'page';
  static const String _subPage = 'subPage';
  static const String _terPage = 'terPage';
  static const String _broadcasterId = 'broadcasterId';
  static const String _duration = 'duration';

  static void stat({
    String? page,
    String? subPage,
    String? terPage,
    String? broadcasterId,
  }) {
    var map = <String, dynamic>{};
    if (page != null) {
      map[_page] = page;
    }
    if (subPage != null) {
      map[_subPage] = subPage;
    }
    if (terPage != null) {
      map[_terPage] = terPage;
    }
    if (broadcasterId != null) {
      map[_broadcasterId] = broadcasterId;
    }
    map[_duration] = 0;
    map[_event] = 'pv';
    map[_tm] = DateTime.now().millisecondsSinceEpoch;

    AFLogManger().putLog(LogType.globalBehavior, map);
  }
}

/// 打点类型
enum LogType {
  globalBehavior('event', 'global_behavior', 'event'),
  clickEvent("event", "click", "event");

  final String logType;
  final String subType;
  final String behavior;

  const LogType(this.logType, this.subType, this.behavior);
}

// 打点管理
class AFLogManger {
  static final AFLogManger _instance = AFLogManger._internal();
  factory AFLogManger() {
    return _instance;
  }
  AFLogManger._internal();

  static const String tag = "AFLogManger"; // 日志标签
  static const int limitSize = 20; // 打点任务最多缓存长度
  static int _serialId = 0;

  final List<Map<String, dynamic>> cacheList = [];
  bool _isWaitingForSend = false; // 是否需要延迟上报

  /// 上报日志
  void putLog(LogType logType, Map<String, dynamic>? event) async {
    if (logType.logType.isEmpty ||
        logType.subType.isEmpty ||
        logType.behavior.isEmpty ||
        event == null ||
        event.isEmpty) {
      return;
    }
    Map<String, dynamic> itemData = await _buildItemData(
        logType.logType, logType.subType, logType.behavior, event);
    cacheList.insert(0, itemData);
    sendDelayed();
  }

  /// 延时发送日志
  void sendDelayed() {
    if (_isWaitingForSend) {
      return;
    }
    _isWaitingForSend = true;
    Timer(const Duration(milliseconds: 2000), () {
      _isWaitingForSend = false;
      sendLog(false);
    });
  }

  /// 发日志打点
  void sendLog(bool forceUploadAll) {
    try {
      List<Map<String, dynamic>> sendList = [];
      if (cacheList.isEmpty) {
        return;
      } else if (cacheList.length >= limitSize && !forceUploadAll) {
        sendList.addAll(cacheList.sublist(0, limitSize));
        cacheList.removeRange(0, limitSize);
      } else {
        sendList.addAll(cacheList);
        cacheList.clear();
      }
      _doUpload(sendList, true);
    } catch (e) {}
  }

  /// 立马发送日志
  void putLogRightNow(LogType logType, Map<String, dynamic>? event) async {
    if (logType.logType.isEmpty ||
        logType.subType.isEmpty ||
        logType.behavior.isEmpty ||
        event == null ||
        event.isEmpty) {
      return;
    }
    Map<String, dynamic> itemData = await _buildItemData(
        logType.logType, logType.subType, logType.behavior, event);
    List<Map<String, dynamic>> list = [];
    list.add(itemData);

    _doUpload(list, false);
  }

  /// 执行上传
  Future<void> _doUpload(
      List<Map<String, dynamic>> sendList, bool isContinue) async {
    var dio = Dio(
      BaseOptions(
        contentType: "application/json",
        receiveTimeout: const Duration(seconds: 30),
        connectTimeout: const Duration(seconds: 30),
      ),
    );
    dio.interceptors.add(HeaderInterceptor());
    dio.post('${AppENV.logUrl}log/live-chat', data: sendList).then((value) {
      if (isContinue) {
        sendDelayed();
      }
    });
  }

  Future<Map<String, dynamic>> _buildItemData(String logType, String subType,
      String behavior, Map<String, dynamic>? event) async {
    String platform = '';
    String model = '';

    final deviceId = await FlutterUdid.udid;
    String launcherId =
        '${DateTime.now().millisecondsSinceEpoch}$deviceId'.md5Str;
    final packageInfo = await PackageInfo.fromPlatform();
    final deviceInfo = DeviceInfoPlugin();
    final iosInfo = await deviceInfo.iosInfo;
    if (Platform.isAndroid) {
      platform = 'Android';
    } else if (Platform.isIOS) {
      platform = 'iOS';
      model = iosInfo.utsname.machine;
    }
    final appStore = GetIt.I.get<AppStore>();
    String version = packageInfo.version;
    String bundleId = packageInfo.packageName;
    String buildNumber = packageInfo.buildNumber;
    Map<String, dynamic> itemData = {};
    itemData[AFLogHeadersKey.afData] = [event];
    itemData[AFLogHeadersKey.afLogType] = logType;
    itemData[AFLogHeadersKey.afSubtype] = subType;
    itemData[AFLogHeadersKey.afBehavior] = behavior;
    itemData[AFLogHeadersKey.afDeviceId] = deviceId;
    itemData[AFLogHeadersKey.afUserId] = appStore.userInfo?.userId ?? '';
    itemData[AFLogHeadersKey.afPkg] = bundleId;
    itemData[AFLogHeadersKey.afChnId] = '';
    itemData[AFLogHeadersKey.afVer] = version;
    itemData[AFLogHeadersKey.afPlatform] = platform;
    itemData[AFLogHeadersKey.afModel] = model;
    itemData[AFLogHeadersKey.afPVer] = buildNumber;
    itemData[AFLogHeadersKey.afLanId] = launcherId;
    itemData[AFLogHeadersKey.afSecId] = _serialId++;
    itemData[AFLogHeadersKey.afsysLan] = appStore.languageCode;
    itemData[AFLogHeadersKey.afCountry] = appStore.languageCode;
    return itemData;
  }
}

extension StringExt on String {
  String get md5Str => md5.convert(utf8.encode(this)).toString();
}

/// 打点请求头key统一传参
class AFLogHeadersKey {
  static const String afData = "data";
  static const String afLogType = "log_type";
  static const String afSubtype = "subtype";
  static const String afBehavior = "behavior";
  static const String afDeviceId = "device-id";
  static const String afAndroidId = "android_id";
  static const String afUserId = "user_id";
  static const String afPkg = "pkg";
  static const String afChnId = "chn_id";
  static const String afVer = "ver";
  static const String afPlatform = "platform";
  static const String afModel = "model";
  static const String afPVer = "p_ver";
  static const String afLanId = "lan_id";
  static const String afSecId = "sec_id";
  static const String afUtmSource = "utm_source";
  static const String afAfAdgroupId = "af_adgroup_id";
  static const String afAfAdset = "af_adset";
  static const String afAfAdsetId = "af_adset_id";
  static const String afAfStatus = "af_status";
  static const String afAfAgency = "af_agency";
  static const String afAfChannel = "af_channel";
  static const String afAfCampaign = "campaign";
  static const String afAfCampaignId = "campaign_id";
  static const String afCountry = "country";
  static const String afsysLan = "sys_lan";
}
